package plgbasev0

import (
	"dgo/goutils/utils"
	"fmt"
	"gitee.com/ymofen/gobase/golog"
	"gitee.com/ymofen/supervalue"
	"reflect"
	"time"
)

type ProjBasePlugin struct {
	PlugId  string // 第一次修改后不可以修改
	PlugDNA uint32 // 外部不可以

	ReleaseFlag int // 外部不可以 1:表示该插件已经释放, 插件一旦释放不会被再次激活(只会创建新的插件)

	Input_ex       interface{}
	input_ex_topic string
	input_ex_subid string

	status_ex          interface{}
	status_ex_id       string
	status_ex_topic    string // 状态数据发布
	status_ex_interval int
	status_ex_task_dna int
	status_out_templ   string
}

func (this *ProjBasePlugin) String() string {
	return fmt.Sprintf("%s", this.PlugId)
}

func (this *ProjBasePlugin) SetPlugID(val string) {
	this.PlugId = val
	this.CheckDNA()
}

func (this *ProjBasePlugin) SetReleaseFlag(val int) {
	this.ReleaseFlag = val
}

func (this *ProjBasePlugin) IsRelease() bool {
	return this.ReleaseFlag == 1
}

func (this *ProjBasePlugin) StatusEx() interface{} {
	return this.status_ex
}

func (this *ProjBasePlugin) StatusExId() string {
	return this.status_ex_id
}

func (this *ProjBasePlugin) StatusExInterval() int {
	return this.status_ex_interval
}

func (this *ProjBasePlugin) CheckDNA() uint32 {
	if this.PlugDNA == 0 {
		this.PlugDNA = utils.NewObjectDNA()
	}
	return this.PlugDNA
}

func (this *ProjBasePlugin) SetStatusEx(val interface{}) {
	this.status_ex = val
	if val == nil {
		return
	}
}

func (this *ProjBasePlugin) ReleaseInput() {
	if len(this.input_ex_subid) == 0 {
		return
	}
	if this.Input_ex == nil {
		return
	}

	if len(this.input_ex_topic) == 0 {
		return
	}

	if sc := GetSubscribeFromVal(this.Input_ex); sc != nil {
		sc.UnsubscribeChannel(this.input_ex_topic, this.input_ex_subid)
		this.input_ex_topic = ""
		this.Input_ex = nil
	}
}

func (this *ProjBasePlugin) CheckMakeInputExSubId(sender interface{}) {
	if len(this.input_ex_subid) == 0 {
		this.input_ex_subid = fmt.Sprintf("%s(%s)-%s", this.PlugId, reflect.TypeOf(sender), utils.RandKeyString(8))
	}
}

/*
*

	{
	 "input":{
	     "id":"ex",
	     "topic":"xxxx"
	  }
	}
*/
func (this *ProjBasePlugin) ReloadInputConf(conf *wrapper.SuperValue, onInput interface{}) (err error) {
	this.CheckDNA()
	ischanged := false
	if len(this.input_ex_subid) == 0 {
		this.input_ex_subid = fmt.Sprintf("%s_%s", this.PlugId, utils.RandKeyString(8))
	}

	var unsubprefn = func() {
		if this.Input_ex != nil {
			if len(this.input_ex_subid) > 0 {
				if sc := GetSubscribeFromVal(this.Input_ex); sc != nil {
					sc.UnsubscribeChannel(this.input_ex_topic, this.input_ex_subid)
				}
			}
		}
	}

	conf.CheckStrFunc("input.id", func(strv string) {
		strv = utils.ReplacePlaceholder(strv, "$$", "$$")
		ex := FindPluginByID(strv)
		if this.Input_ex != ex {
			if this.Input_ex != nil {
				unsubprefn()
				this.Input_ex = nil
			}
			this.Input_ex = ex
			ischanged = true
		}
	})

	conf.CheckStrFunc("input.topic", func(strv string) {
		strv = utils.ReplacePlaceholder(strv, "$$", "$$")
		if this.input_ex_topic != strv {
			unsubprefn()
			this.input_ex_topic = strv
			ischanged = true
		}
	})

	if ischanged {
		if len(this.input_ex_topic) > 0 && this.Input_ex != nil {
			if fn, ok2 := onInput.(utils.SubscribeCallback); ok2 {
				utils.TrySubscribeChannel(this.Input_ex, this.input_ex_topic, this.input_ex_subid, fn)
			} else {
				golog.Warnf("订阅函数非SubscribeCallback")
			}

			//if sc := GetSubscribeFromVal(this.Input_ex); sc != nil {
			//	if fn, ok2 := onInput.(utils.SubscribeCallback); ok2 {
			//		sc.SubscribeChannel(this.input_ex_topic, this.input_ex_subid, fn)
			//	} else {
			//		golog.Warnf( "订阅函数非SubscribeCallback")
			//	}
			//}
		}
	}
	return
}

func (this *ProjBasePlugin) StatusOStatusString() string {
	if len(this.status_ex_id) == 0 {
		return ""
	} else {
		if this.status_ex == nil {
			return fmt.Sprintf("%s(nil)", this.status_ex_id)
		} else {
			return fmt.Sprintf("%s(%p)", this.status_ex_id, this.status_ex)
		}
	}
}

/*
*

	{
	 "status_o":{
	     "id":"ex",
	     "topic":"xxxx",
	     "interval":1,
	     "templ":{}
	  }
	}

	status_fn_shutdown 表示关闭
	status_fn_start 开启
*/
func (this *ProjBasePlugin) ReloadStatusOConf(conf *wrapper.SuperValue,
	status_fn func(), status_fn_start func(), status_fn_shutdown func()) (err error) {

	conf.CheckExistsStrFunc("status_o.templ", func(strv string) {
		this.status_out_templ = strv
	})

	conf.CheckStrFunc("status_o.id", func(strv string) {
		this.status_ex_id = strv
		ex := FindPluginByID(strv)
		this.SetStatusEx(ex)
	})
	conf.CheckStrFunc("status_o.topic", func(strv string) {
		this.status_ex_topic = strv
	})

	conf.CheckExistsIntFunc("status_o.interval", func(val int64) {
		if this.status_ex_interval != int(val) {
			this.status_ex_task_dna++
			if this.status_ex_interval <= 0 { // 之前关闭
				if status_fn_start != nil {
					status_fn_start()
				}
			}
			this.status_ex_interval = int(val)
			if this.status_ex_interval > 0 {
				dna := this.status_ex_task_dna
				this.CheckDNA()
				utils.AddTaskFxiedInterval(fmt.Sprintf("plugin_%d", this.PlugDNA),
					time.Duration(this.status_ex_interval)*time.Second, func() bool {
						if dna != this.status_ex_task_dna || this.ReleaseFlag == 1 {
							if status_fn_shutdown != nil {
								status_fn_shutdown()
							}
							return false
						}
						if status_fn != nil {
							status_fn()
						}
						return true
					})
			} else {
				if status_fn_shutdown != nil {
					status_fn_shutdown()
				}
			}

		}

	})
	return
}

func (this *ProjBasePlugin) SendStatus(msg string) {
	ex := this.status_ex
	if ex == nil {
		ex = FindPluginByID(this.status_ex_id)
		if ex != nil {
			this.status_ex = ex
		}
	}
	if ex == nil {
		return
	}
	if sc, ok := ex.(IDispatchData); ok {
		sc.DispatchData(this.status_ex_topic, this, msg, nil)
	} else if sc, ok := ex.(IGetSubscriber); ok {
		sc.GetSubscriber().DispatchData(this.status_ex_topic, this, msg, nil)
	} else if sc, ok := ex.(utils.SubscribeCenter); ok {
		sc.DispatchData(this.status_ex_topic, this, msg, nil)
	} else if sc, ok := ex.(ISendKVs); ok {
		sc.SendKVs(this.status_ex_topic, msg)
	}
}

func (this *ProjBasePlugin) SendStatusFunc(fillStatus func(json *wrapper.SuperValue)) {
	ex := this.status_ex
	if ex == nil {
		ex = FindPluginByID(this.status_ex_id)
		if ex != nil {
			this.status_ex = ex
		}
	}
	if ex == nil {
		return
	}

	if sc, ok := ex.(IDispatchData); ok {
		json := wrapper.NewSVObject()
		if len(this.status_out_templ) > 0 {
			json.JsonParserFromByte([]byte(this.status_out_templ))
		}
		fillStatus(json)
		sc.DispatchData(this.status_ex_topic, this, json, nil)
	} else if sc, ok := ex.(IGetSubscriber); ok {
		json := wrapper.NewSVObject()
		if len(this.status_out_templ) > 0 {
			json.JsonParserFromByte([]byte(this.status_out_templ))
		}

		fillStatus(json)
		sc.GetSubscriber().DispatchData(this.status_ex_topic, this, json, nil)
	} else if sc, ok := ex.(utils.SubscribeCenter); ok {
		json := wrapper.NewSVObject()
		if len(this.status_out_templ) > 0 {
			json.JsonParserFromByte([]byte(this.status_out_templ))
		}

		fillStatus(json)
		sc.DispatchData(this.status_ex_topic, this, json, nil)
	} else if sc, ok := ex.(ISendKVs); ok {
		json := wrapper.NewSVObject()
		if len(this.status_out_templ) > 0 {
			json.JsonParserFromByte([]byte(this.status_out_templ))
		}
		fillStatus(json)
		sc.SendKVs(this.status_ex_topic, json)
	}
}
